import { VxeColumnSlots } from 'vxe-table'
import { ElTag as ElTagComp } from 'element-plus'
import {
  getComponentProps,
  getComponentEvents,
  getComponentSlots,
  createDefaultEvent,
  type RenderTableCellOptions,
  type RenderTableCellParams,
  type ComponentParams
} from './common'

type RenderCellTagMapData = { label: string; value: string | number; color?: string }[]
type ValueMethod = {
  ({ row, column, cellVal, cellLabelVal }): string
}
type LabelMethod = {
  ({ row, column, cellVal, cellLabelVal }): string | boolean | undefined | null
}
type ShowMethod = {
  ({ row, column, cellVal, cellLabelVal }): boolean
}
type RenderCellTagOptions = {
  key?: string
  labelKey?: string
  isTag?: boolean
  /** 自定义取值处理方法 */
  valueMethod?: ValueMethod
  /** 自定义显示值处理方法 */
  labelMethod?: LabelMethod
  /** 标签是否显示 */
  showMethod?: ShowMethod
}

/** 读取对应的label */
const selectDictLabel = function (mapData, val, key = 'label') {
  if (!Object.keys(mapData).includes(String(val))) return val
  return mapData[val][key]
}

const transMapData = function (mapData: RenderCellTagMapData) {
  return mapData.reduce((prev, curr) => {
    prev[curr.value] = curr
    return prev
  }, {})
}

/**
 * @description vxe表格渲染对应的tag
 * @param {RenderCellTagMapData} mapData map对象 在constant.ts文件中定义
 * @param {RenderCellTagOptions} options 配置项 可以不传
 * @param {string} options.key 字段的key,默认为当前列的field
 * @param {string} options.isTag 是否为标签,默认为true
 * @param {LabelMethod} options.labelMethod 处理显示值的方法
 * @param {ValueMethod} options.valueMethod 处理取值的方法,特殊情况会用的,比如根据是否存在返回对应值
 * @returns {VxeColumnSlots['default']}
 * @example
   import { renderCellTag } from '/@/utils';
   slots: {
     default: renderCellTag(prodStatus),
   },
 */
export const renderCellTag = function (
  mapData: RenderCellTagMapData,
  options?: RenderCellTagOptions
): VxeColumnSlots['default'] {
  mapData = mapData ? transMapData(mapData) : {}
  return function ({ row, column }) {
    if (options) {
      const {
        key,
        labelKey,
        isTag = true,
        labelMethod = null,
        valueMethod = null,
        showMethod = null
      } = options
      const props = key || column.field
      // 当行原始数据
      const cellVal = row[props]
      const cellLabelVal = labelKey ? row[labelKey] : cellVal
      // 对显示值进行处理
      const formatterStr = labelKey
        ? labelMethod
          ? labelMethod({ row, column, cellVal, cellLabelVal })
          : row[labelKey]
        : labelMethod && labelMethod({ row, column, cellVal, cellLabelVal })
      // 自定义值处理方法
      const showVal = valueMethod ? valueMethod({ row, column, cellVal, cellLabelVal }) : cellVal
      // 是否展示
      const show = showMethod ? showMethod({ row, column, cellVal, cellLabelVal }) : true
      if (!show) return ''
      // 如果不包含则展示 formatterStr数据 或 showVal数据
      if (!Object.keys(mapData).includes(String(showVal))) return formatterStr ?? showVal
      // 展示文字
      const showStr = formatterStr ?? mapData[showVal]['label']
      // 处理formatter 用于客户端导出 也可以兼容筛选器
      column.formatter = column.formatter
        ? column.formatter
        : ({ row, column, cellValue }) =>
            selectDictLabel(
              mapData,
              labelMethod
                ? labelMethod({ row, column, cellVal: cellValue, cellLabelVal })
                : valueMethod
                  ? valueMethod({ row, column, cellVal: cellValue, cellLabelVal })
                  : cellValue
            )
      if (isTag) {
        return <ElTagComp type={mapData[showVal]['color']}>{showStr}</ElTagComp>
      } else {
        return showStr
      }
      // }
    } else {
      const props = column.field
      // const cellVal = row[props];
      // 获取到的props可能是xxx.xxx的形式,需要处理一下
      let cellVal = ''
      if (props.includes('.')) {
        const propsArr = props.split('.')
        cellVal = _.get(row, propsArr)
      } else {
        cellVal = row[props]
      }
      // 处理formatter 用于客户端导出 也可以兼容筛选器
      column.formatter = column.formatter
        ? column.formatter
        : ({ cellValue }) => selectDictLabel(mapData, cellValue)
      if (!Object.keys(mapData).includes(String(cellVal))) return cellVal
      // return h(Tag, { color: mapData[cellVal]['color'] }, () => mapData[cellVal]['label']);
      // 不展示tag 客户显示器看不到
      return mapData[cellVal]['label']
    }
  }
}

const ElTag = {
  renderTableDefault(renderOpts: RenderTableCellOptions, params: RenderTableCellParams) {
    const { $grid, column, row } = params

    // 默认属性
    const defaultProps = {}
    // 需要自定义的事件
    const omitEventsKeys = []

    const { options } = renderOpts

    const renderer = renderCellTag(options || [], {
      ...getComponentProps(renderOpts, defaultProps)
    })

    return renderer!({ row, column })
  }
}

export default {
  ElTag
}
